﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.Reflection;
using System.Drawing;
using System.Xml;
using System.IO;
using VirusCleaner.IPlugin;
using VirusCleaner.IPlugin.Plugin;
using VirusCleaner.Update;
using VirusCleaner.BugReport;
using VirusCleaner.SysMenu;
using VirusCleaner.Language;
using VirusCleaner.IPlugin.Host;
using MessageBox = VirusCleaner.Controls.Forms.MessageBox;

namespace VirusCleaner.Center.Froms
{
    public partial class FrmMain : Form, IUiElementHost
    {
        private Updater _updater;
        private readonly string[] _args;
        private readonly ILogService _logging;
        private readonly List<IUiElement> _uiElement;

        #region 构建函数


        /// <summary>
        /// 窗体构建
        /// </summary>
        private void InitializeComponent()
        {
            var resources = new ComponentResourceManager(typeof(FrmMain));
            _statusStrip = new StatusStrip();
            _lblVersion = new ToolStripStatusLabel();
            _lblVerNum = new ToolStripStatusLabel();
            _pbrUpdateProgress = new ToolStripProgressBar();
            _lblCheckUpdate = new ToolStripStatusLabel();
            _toolStrip = new ToolStrip();
            _tabControlMain = new Controls.TabControl();
            _statusStrip.SuspendLayout();
            SuspendLayout();
            // 
            // _statusStrip
            // 
            _statusStrip.Items.AddRange(new ToolStripItem[] {
            _lblVersion,
            _lblVerNum,
            _pbrUpdateProgress,
            _lblCheckUpdate});
            _statusStrip.Location = new Point(0, 510);
            _statusStrip.Name = "_statusStrip";
            _statusStrip.Size = new Size(784, 22);
            _statusStrip.TabIndex = 5;
            // 
            // _lblVersion
            // 
            _lblVersion.Name = "_lblVersion";
            _lblVersion.Size = new System.Drawing.Size(77, 17);
            _lblVersion.Text = "${VERSION}";
            // 
            // _lblVerNum
            // 
            _lblVerNum.Name = "_lblVerNum";
            _lblVerNum.Size = new System.Drawing.Size(73, 17);
            _lblVerNum.Text = ProductVersion;
            // 
            // _pbrUpdateProgress
            // 
            _pbrUpdateProgress.Name = "_pbrUpdateProgress";
            _pbrUpdateProgress.Size = new System.Drawing.Size(100, 16);
            _pbrUpdateProgress.Visible = false;
            // 
            // _lblCheckUpdate
            // 
            _lblCheckUpdate.IsLink = true;
            _lblCheckUpdate.LinkBehavior = System.Windows.Forms.LinkBehavior.HoverUnderline;
            _lblCheckUpdate.Name = "_lblCheckUpdate";
            _lblCheckUpdate.Size = new System.Drawing.Size(115, 17);
            _lblCheckUpdate.Text = @"${UPDATE_CHECK}";
            _lblCheckUpdate.Click += new System.EventHandler(LnkUpdateClick);
            // 
            // _toolStrip
            // 
            _toolStrip.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(224)))), ((int)(((byte)(192)))));
            _toolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
            _toolStrip.ImageScalingSize = new System.Drawing.Size(50, 50);
            _toolStrip.Location = new System.Drawing.Point(0, 0);
            _toolStrip.Name = "_toolStrip";
            _toolStrip.Padding = new System.Windows.Forms.Padding(10, 10, 3, 10);
            _toolStrip.RenderMode = System.Windows.Forms.ToolStripRenderMode.System;
            _toolStrip.Size = new System.Drawing.Size(784, 25);
            _toolStrip.TabIndex = 0;
            _toolStrip.Text = "";
            _toolStrip.ItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(ToolStripItemClicked);
            // 
            // _tabControlMain
            // 
            _tabControlMain.Alignment = System.Windows.Forms.TabAlignment.Bottom;
            _tabControlMain.Dock = System.Windows.Forms.DockStyle.Fill;
            _tabControlMain.HideTabs = true;
            _tabControlMain.Location = new System.Drawing.Point(0, 25);
            _tabControlMain.Margin = new System.Windows.Forms.Padding(0);
            _tabControlMain.Multiline = true;
            _tabControlMain.Name = "_tabControlMain";
            _tabControlMain.Padding = new System.Drawing.Point(0, 0);
            _tabControlMain.SelectedIndex = 0;
            _tabControlMain.ShowToolTips = true;
            _tabControlMain.Size = new System.Drawing.Size(784, 485);
            _tabControlMain.TabIndex = 4;
            // 
            // FrmMain
            // 
            AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            ClientSize = new System.Drawing.Size(784, 532);
            Controls.Add(_tabControlMain);
            Controls.Add(_statusStrip);
            Controls.Add(_toolStrip);
            Icon = ((Icon)(resources.GetObject("$Icon")));
            MinimumSize = new Size(800, 570);
            Name = "FrmMain";
            StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
            Text = @"${MAIN_TITLE}";
            FormClosed += FrmMain_FormClosed;
            Load += FrmMain_Load;
            _statusStrip.ResumeLayout(false);
            _statusStrip.PerformLayout();
            ResumeLayout(false);
            PerformLayout();

        }

        private ToolStripStatusLabel _lblVersion;
        private ToolStripStatusLabel _lblVerNum;
        private ToolStripProgressBar _pbrUpdateProgress;
        private ToolStripStatusLabel _lblCheckUpdate;
        private readonly IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
        private ToolStrip _toolStrip;
        private StatusStrip _statusStrip;
        private Controls.TabControl _tabControlMain;


        #region 创建菜单

        private SystemMenuNativeWindow _systemMenuNativeWindow;
        protected override void OnCreateControl()
        {
            base.OnCreateControl();

            if (_systemMenuNativeWindow == null)
            {
                _systemMenuNativeWindow = new SystemMenuNativeWindow(this);
            }
            _systemMenuNativeWindow.AppendSeparator();
            _systemMenuNativeWindow.AppendMenu(
                1000,
                string.Format("关于 {0} (&A)...", Text),
                (sender, args) => VirusCleaner.Controls.Forms.AboutMeBox.Show());
        }
        protected override void OnHandleDestroyed(EventArgs e)
        {
            base.OnHandleDestroyed(e);
            if (_systemMenuNativeWindow != null)
            {
                _systemMenuNativeWindow.Dispose();
                _systemMenuNativeWindow = null;
            }
        }
        #endregion
        #endregion
        #region 处理参数
        public FrmMain(string[] args, ILogService logging)
        {
            _args = args;
            _logging = logging;
            _uiElement = new List<IUiElement>();
            InitializeComponent();
        }
        private void FrmMain_FormClosed(object sender, FormClosedEventArgs e)
        {
#if !DEBUG
            Process.Start("VirusCleanerTray.exe");
#endif
        }
        #endregion
        #region 加载项目
        /// <summary>
        /// The logging service to use.
        /// </summary>
        private void FrmMain_Load(object sender, EventArgs e)
        {
            LoadPlugins("Config.xml");
            LanguageString.ApplyResource(this);
        }
        #endregion
        
        #region 加载组件
        
        private void ToolStripItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            var index = (int)e.ClickedItem.Tag;
            _tabControlMain.SelectTab(index);
            for (int i = 0; i < _uiElement.Count; i++)
            {
                IUiElement ui = _uiElement[i];
                ui.Active(index == i);
            }
        }
        #endregion
        #region 检查更新
        ToolStripStatusLabel _lblOk, _lblCancel;
        private void LnkUpdateClick(object sender, EventArgs e)
        {
            _updater = new Updater(Application.ExecutablePath);
            _updater.StateChanged += AppStateChanged;
            try
            {
                if (_lblCheckUpdate.IsLink && _updater.CheckUpdate())
                {
                    _lblCheckUpdate.IsLink = false;
                    _lblCheckUpdate.Text = string.Format("检测到新版本:{0},是否更新?", _updater.GetVersion());
                    _lblOk = new ToolStripStatusLabel("确定") { IsLink = true };
                    _lblOk.Click += LblClick;
                    _statusStrip.Items.Add(_lblOk);
                    _lblCancel = new ToolStripStatusLabel("取消") { IsLink = true };
                    _lblCancel.Click += LblClick;
                    _statusStrip.Items.Add(_lblCancel);
                }
                else
                {
                    _lblCheckUpdate.Text = string.Format("{0}", LanguageString.Parse("${UPDATE_NEW}"));
                }
            }
            catch (Exception ex)
            {
                _logging.WriteException("Message", ex);
            }
        }
        void LblClick(object sender, EventArgs e)
        {
            var lbl = sender as ToolStripLabel;
            _lblOk.Visible = false;
            _lblCancel.Visible = false;
            if (lbl != null)
                if (lbl.Text.Equals("确定"))
                {
                    _pbrUpdateProgress.Visible = true;
                    _updater.Update();
                }
                else
                {
                    _lblCheckUpdate.IsLink = true;
                    _lblCheckUpdate.Text = @"检查更新";
                }
        }
        void AppStateChanged(long value, long max, int bytes)
        {
            _pbrUpdateProgress.Maximum = (int)max;
            _pbrUpdateProgress.Value = (int)value;
            _lblCheckUpdate.Text = string.Format("正在更新:{0:0%}速度:{1}/Kbps", (double)value / max, bytes / 1024);
            if (value == max)
            {
                if (MessageBox.Show(
                    LanguageString.Parse("${UPDATE_DONE}"),
                    LanguageString.Parse("${UPDATE_TITLE}"),
                    "确定(&O)", "取消(&C)") == DialogResult.OK)
                {
                    Application.Restart();
                }
                _lblCheckUpdate.IsLink = true;
                _lblCheckUpdate.Text = @"检查更新";
                _pbrUpdateProgress.Visible = false;
            }
        }
        #endregion
        #region IUiHost 成员

        public List<IUiElement> Plugins
        {
            get { return _uiElement; }
        }
        public IUiElement GetPlugin(string name)
        {
            if (String.IsNullOrEmpty(name))
                throw new ArgumentException();
            return _uiElement.Find(x => x.PluginName.Equals(name));
        }
        private void InitAddin()
        {
            _uiElement.ForEach(x => x.Init());
        }

        #endregion

        #region IHost 成员
        public int LoadPlugins(string xmlfile)
        {
            var xmlDoc = new XmlDocument();
            xmlDoc.Load(xmlfile);
            var xn = xmlDoc.SelectSingleNode("Config");
            if (xn.Attributes["name"].InnerText == ProductName)
            {
                xn = xn.SelectSingleNode("Addin");
                foreach (XmlNode xnn in xn.ChildNodes)
                {
                    string name = xnn.Attributes["name"].Value;
                    string file = xnn.Attributes["dll"].Value;
                    string icon = xnn.Attributes["icon"].Value;
                    string desc = xnn.Attributes["desc"].Value;
                    ;
                    //创建TabPage容器
                    var tab = new TabPage(name);

                    var btn = new ToolStripButton
                    {
                        Text = name,
                        ToolTipText = desc,
                        Tag = _tabControlMain.TabPages.Count,
                        Margin = new Padding(0, 0, 10, 0),
                        TextImageRelation = TextImageRelation.ImageAboveText
                    };

                    if (File.Exists(file))
                    {
                        Assembly assembly = Assembly.LoadFrom(file);
                        Stream stream = assembly.GetManifestResourceStream(icon);
                        btn.Image = stream != null ? Image.FromStream(stream) : Properties.Resources.Default;
                        foreach (Type t in assembly.GetTypes())
                        {
                            //验证是否符合接口规范
                            if (!t.IsClass ||
                                !(typeof(IUiElement).IsAssignableFrom(t) && typeof(UserControl).IsAssignableFrom(t)))
                                continue;
                            //获得加载控件
                            var ctrl = (Activator.CreateInstance(t)) as UserControl;
                            _uiElement.Add((IUiElement)ctrl);
                            if (ctrl != null)
                            {
                                //设置填充样式
                                ctrl.Dock = DockStyle.Fill;
                                //添加控件到容器
                                tab.Controls.Add(ctrl);
                            }
                            _toolStrip.Items.Add(btn);
                            //添加TabPage到父容器
                            _tabControlMain.TabPages.Add(tab);
                        }
                    }
                }
                InitAddin();
            }
            return _uiElement.Count;
        }
        #endregion
    }
}
